package route

import (
	Middlewares "AI/Middlewares"
	"fmt"
	"reflect"
	"strings"

	"github.com/gin-gonic/gin"
)

type Route struct {
	path       string         //url路径
	httpMethod string         // method
	Method     reflect.Value  //方法路由
	Args       []reflect.Type //参数类型
}

var Routes = []Route{}

func InitRouter() *gin.Engine {
	r := gin.Default()
	Bind(r)
	return r
}

// 绑定基础路由
func Bind(e *gin.Engine) {
	for _, route := range Routes {
		if route.httpMethod == "GET" {
			e.GET(route.path, Middlewares.TotalTime, match(route.path, route))
		}
		if route.httpMethod == "POST" {
			e.POST(route.path, Middlewares.TotalTime, match(route.path, route))
		}
	}
}

// 注册控制器
func Register(controller interface{}) bool {
	// 取来源
	ctrlName := reflect.TypeOf(controller).String()
	fmt.Println("ctrlName1=", ctrlName)
	module := ctrlName
	//  是否存在.
	if strings.Contains(ctrlName, ".") {
		module = ctrlName[strings.Index(ctrlName, ".")+1:]
	}
	fmt.Println("module=", module)
	v := reflect.ValueOf(controller)

	//  导出两个方法
	for i := 0; i < v.NumMethod(); i++ {
		method := v.Method(i)
		action := v.Type().Method(i).Name
		// 路径
		// path := "/serve/" + module + "/" + strings.ToLower(action)
		path := "/" + module + "/" + strings.ToLower(action)
		// 遍历参数
		params := make([]reflect.Type, 0, v.NumMethod())
		httpMethod := "POST"
		if strings.Contains(action, "_get") {
			httpMethod = "GET"
		}
		for j := 0; j < method.Type().NumIn(); j++ {
			params = append(params, method.Type().In(j))
			//   接受类型
		}

		route := Route{path: path, Method: method, Args: params, httpMethod: httpMethod}

		Routes = append(Routes, route)
	}
	fmt.Println("Routes=", Routes)
	return true
}

// 路由控制器
func match(path string, route Route) gin.HandlerFunc {

	return func(c *gin.Context) {
		fields := strings.Split(path, "/")
		fmt.Println("fileds,len(fileds)=", fields, len(fields))
		if len(fields) < 3 {
			return
		}
		fmt.Println(len(Routes))
		if len(Routes) > 0 {
			arguments := make([]reflect.Value, 1)
			arguments[0] = reflect.ValueOf(c) //*gin.Context
			route.Method.Call(arguments)
		}
	}
}
